<template>
  <div>
    <el-dialog
      :title="data.id ? '编辑' : '创建'"
      :visible.sync="dialogVisible"
      :fullscreen="config.fullscreen"
    >
      <el-form
        ref="dataForm"
        :rules="formRules"
        :model="formData"
        label-position="right"
        :label-width="`${config.labelWidth || 80}px`"
      >
        <template>
          <FormItems
            v-model="formData"
            :columns="columns"
            :select-options="selectOptions"
          />
        </template>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submit">
          确认
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import FormItems from '@/components2/FormItems'

export default {
  name: 'FormDialog',
  components: { FormItems },
  directives: {},
  filters: {},

  props: {
    visible: { type: Boolean, default: () => false },

    data: {
      type: Object,
      default: () => {
        return {}
      }
    },

    columns: { type: Array, default: () => [] },
    config: {
      type: Object,
      default: () => {
        return {}
      }
    }
  },

  data() {
    return {
      dialogVisible: false,

      formData: {},

      asyncSelectOptions: {},

      formRules: {
        // type: [{ required: true, message: 'type is required', trigger: 'change' }],
        // timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }],
        // title: [{ required: true, message: 'title is required', trigger: 'blur' }]
      }
    }
  },

  computed: {
    //
    //
    selectOptions: function() {
      // 下拉框选择项计算函数，
      // 首先取 options；其次，取自 函数 computedOptions；再次，取自 asyncSelectOptions
      // computedOptions 函数 需要参数 asyncSelectOptions

      return this.columns.reduce((acc, col) => {
        if (['select', 'select2', 'radio'].includes(col.type)) {
          let options = []
          const asyncOptions = this.asyncSelectOptions[col.name] || []

          if (col.options) {
            options = col.options()
          } else if (col.computedOptions) {
            options = col.computedOptions({
              options: asyncOptions,
              row: this.formData
            })
          } else if (asyncOptions) {
            options = asyncOptions
          }

          acc[col.name] = options
        }

        return acc
      }, {})
    }
  },

  watch: {
    data(val) {
      //
      if (this.data.id) {
        this.formData = this.columns.reduce(
          (res, col) => {
            res[col.name] = this.data[col.name]
            return res
          },
          { id: this.data.id }
        )
      } else {
        this.formData = this.columns.reduce((res, col) => {
          if (col.default !== undefined) {
            if (typeof col.default === 'function') {
              res[col.name] = col.default()
            } else {
              res[col.name] = col.default
            }
          }
          return res
        }, {})
      }
    },

    visible(val) {
      this.dialogVisible = this.visible
    },

    dialogVisible(val) {
      this.$emit('update:visible', this.dialogVisible)
    }
  },

  async created() {
    //
    this.setSelectOptions()
  },

  methods: {
    //
    async setSelectOptions() {
      // 下拉框选择项, 如果需要异步操作, 则在打开窗口前， 根据异步参数或异步函数获取数据，并暂存。
      // 页面在渲染时，根据需要读取

      const selectOptions = {}
      let selectOptionsParams = {}

      for (const col of this.columns) {
        if (['select', 'select2', 'radio'].includes(col.type)) {
          // console.log('xxxxx, col.asyncOptionsParams', col.asyncOptionsParams)
          if (col.asyncOptionsParams) {
            selectOptionsParams = {
              ...selectOptionsParams,
              ...col.asyncOptionsParams
            }
          } else if (col.asyncOptions) {
            selectOptions[col.name] = await col.asyncOptions()
          }
        }
      }

      const fromParent = Object.keys(selectOptionsParams).length
        ? await this.$parent.asyncSelectOptions(selectOptionsParams)
        : {}

      this.asyncSelectOptions = { ...fromParent, ...selectOptions }
      // console.log('xxxxx, this.asyncSelectOptions', this.asyncSelectOptions)
    },

    submit() {
      this.$refs['dataForm'].validate(async valid => {
        if (valid) {
          // console.log('xxxxx,submit ', this.formData)
          this.$emit('submit', this.formData)
        }
      })
    }
  }
}
</script>
